package net.wanglu.www.zzz.rule.artcl;

import java.util.regex.Pattern;

import net.wanglu.www.zzz.rule.BadEgg;
import net.wanglu.www.zzz.rule.Rule;
import net.wanglu.www.zzz.service.se.np._NPTuple;
import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.tregex.TregexMatcher;
import edu.stanford.nlp.trees.tregex.TregexPattern;

public class Islands extends _ArticleRule {

	public Pattern TheIsland = Pattern.compile("\\bNorth Jutlandic\\b|\\bNorth\\b|\\bSouth\\b");
	public Pattern Island = Pattern.compile("\\b[Ii]sland\\b");
	public Pattern NoTheIslands = Pattern.compile("\\bBacan islands\\b|\\bSouth Georgia and the South Sandwich Islands\\b");
	public Pattern Islands = Pattern.compile("\\b[Ii]slands\\b");
	public Pattern NoTheNoBoth = Pattern.compile("\\bGreenland\\b|\\bNew Guinea\\b|\\bBorneo\\b|\\bMadagascar\\b|\\bSumatra\\b|\\bHonshu\\b|\\bGreat Britain\\b|\\bSulawesi\\b|\\bJava\\b|\\bLuzon\\b|\\bNewfoundland\\b|\\bCuba\\b|\\bIceland\\b|\\bMindanao\\b|\\bIreland\\b|\\bHokkaido\\b|\\bHispaniola\\b|\\bSakhalin\\b|\\bSri Lanka\\b|\\bTasmania\\b|\\bTierra del Fuego\\b|\\bMarajó\\b|\\bSpitsbergen\\b|\\bKyushu\\b|\\bTaiwan\\b|\\bNew Britain\\b|\\bHainan\\b|\\bTimor\\b|\\bSicily\\b|\\bSardinia\\b|\\bShikoku\\b|\\bHalmahera\\b|\\bNordaustlandet\\b|\\bSumbawa\\b|\\bFlores\\b|\\bNegros\\b|\\bSamar\\b|\\bPanay\\b|\\bTupinambarana\\b|\\bJamaica\\b|\\bSumba\\b|\\bMindoro\\b|\\bViti Levu\\b|\\bHawaii\\b|\\bCyprus\\b|\\bNew Caledonia\\b|\\bPuerto Rico\\b|\\bCorsica\\b|\\bBuru\\b|\\bCrete\\b|\\bNew Ireland\\b|\\bLeyte\\b|\\bEast Falkland\\b|\\bZealand\\b|\\bNew Siberia\\b|\\bVanua Levu\\b|\\bBali\\b|\\bGuadalcanal\\b|\\bTrinidad\\b|\\bIlha Grande do Gurupá\\b|\\bLombok\\b|\\bWest Falkland\\b|\\bBelitung\\b|\\bCebu\\b|\\bMadura\\b|\\bButon\\b|\\bHoste\\b|\\bNias\\b|\\bEspiritu Santo\\b|\\bMilne Land\\b|\\bMalaita\\b|\\bSiberut\\b|\\bBohol\\b|\\bMajorca\\b|\\bEuboea\\b|\\bSocotra\\b|\\bWetar\\b|\\bIturup\\b|\\bMakira\\b|\\bWaigeo\\b|\\bYamdena\\b|\\bGotland\\b|\\bFunen\\b|\\bTaliabu\\b|\\bMuna\\b|\\bZemlya Georga\\b|\\bSaaremaa\\b|\\bObira\\b|\\bRéunion\\b|\\bParamushir\\b|\\bPeleng\\b|\\bGroote Eylandt\\b|\\bYapen\\b|\\bMorotai\\b|\\bIsla de la Juventud\\b|\\bWilczek Land\\b|\\bHinnøya\\b|\\bLewis and Harris\\b|\\bTrangan\\b|\\bAlor\\b|\\bLaut\\b|\\bNew Georgia\\b|\\bMisool\\b|\\bTenerife\\b|\\bBioko\\b|\\bCaviana\\b|\\bBiak\\b|\\bMaui\\b|\\bŽitný ostrov\\b|\\bMauritius\\b|\\bJeju Province\\b|\\bAfognak\\b|\\bUmnak\\b|\\bBolshoy Shantar\\b|\\bBolshoy Begichev\\b|\\bSimeulue Regency\\b|\\bRakiura\\b|\\bKobroor\\b|\\bNatuna Besar\\b|\\bSavai'i\\b|\\bFuerteventura\\b|\\bZanzibar\\b|\\bSkye\\b|\\bSoisalo\\b|\\bLesbos\\b|\\bSalawati\\b|\\bTanahbesar\\b|\\bOahu\\b|\\bRantau\\b|\\bSenja\\b|\\bGran Canaria\\b|\\bInagua\\b|\\bGreat Karimun\\b|\\bCatanduanes\\b|\\bRupat\\b|\\bAndros\\b|\\bKauai\\b|\\bUrup\\b|\\bRhodes\\b|\\bÖland\\b|\\bQeshm\\b|\\bBarentsøya\\b|\\bLembata\\b|\\bBasilan\\b|\\bShannon\\b|\\bMorfil\\b|\\bLolland\\b|\\bGrande Comore\\b|\\bÎle Vanier\\b|\\bUpolu\\b|\\bMartinique\\b|\\bGrand Bahama\\b|\\bHecla-Grindstone Provincial Park\\b|\\bSääminginsalo\\b|\\bGreat Nicobar\\b|\\bTahiti\\b|\\bChongming\\b|\\bMaya Karimata\\b|\\bSantiago\\b|\\bHiiumaa\\b|\\bMarinduque\\b|\\bIsla Ángel de la Guarda\\b|\\bUmboi\\b|\\bBengkalis Regency\\b|\\bRügen\\b|\\bRangsang\\b|\\bEfate\\b|\\bSouth Pagai\\b|\\bAttu\\b|\\bErromango\\b|\\bKabaena\\b|\\bJolo\\b|\\bVanatinai\\b|\\bLangøya\\b|\\bSado\\b|\\bKarakelong\\b|\\bLanzarote\\b|\\bChios\\b|\\bSørøya\\b|\\bSangmissoq\\b|\\bSanto Antão\\b|\\bCephalonia\\b|\\bSingkep\\b|\\bSão Miguel Island\\b|\\bMadeira\\b|\\bLittle Andaman\\b|\\bKvaløya\\b|\\bOlkhon\\b|\\bPantar\\b|\\bWowoni\\b|\\bAnglesey\\b|\\bAmami Ōshima\\b|\\bLa Palma\\b|\\bPulau Ujong\\b|\\bKomoran\\b|\\bMinorca\\b|\\bKolombangara\\b|\\bFasta Åland\\b|\\bKvitøya\\b|\\bAmbrym\\b|\\bMolokai\\b|\\bRingvassøy\\b|\\bCozumel\\b|\\bLondonderry\\b|\\bKiritimati\\b|\\bBoa Vista\\b|\\bSamosir\\b|\\bPolillo\\b|\\bVella Lavella\\b|\\bNorth Pagai\\b|\\bSaint Lucia\\b|\\bIslay\\b|\\bStore Koldewey\\b|\\bPrins Karls Forland\\b|\\bSipura\\b|\\bCorfu\\b|\\bGrande-Terre\\b|\\bBornholm\\b|\\bTawi-Tawi\\b|\\bMajuli\\b|\\bBahrain\\b|\\bIbiza\\b|\\bHitra\\b|\\bGuimaras\\b|\\bSeiland\\b|\\bSanana\\b|\\bTanna\\b|\\bEmerald Isle\\b|\\bSangir Besa\\b|\\bKai Besar\\b|\\bSan Cristóbal\\b|\\bPhuket\\b|\\bGuam\\b|\\bIsle Royale\\b|\\bIsla de los Estados\\b|\\bUkerewe\\b|\\bAustvågøy\\b|\\bKimitoön\\b|\\bYakushima\\b|\\bPhú Quốc\\b|\\bFalster\\b|\\bDjerba\\b|\\bAdonara\\b|\\bVangunu\\b|\\bAcklins\\b|\\bNendo\\b|\\bCoiba\\b|\\bBiliran\\b");
	public Pattern TheNoBoth = Pattern.compile("\\bIsle of Mull\\b|\\bMainland\\b|\\bFlevopolder\\b");

	@Override
	public Object applicable(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		_NPTuple npt = (_NPTuple) objects[1];
		Tree NP = npt.getNP();
		if ( NP.depth() != 2) return Rule.Inapplicable;//如果不是叶子节点的父母则不符合要求
		TaggedWord headword = npt.getHeadword();
		if ( headword.tag().startsWith("NN")) {
			return Rule.Applicable;//如果中心词是名词则符合要求，否则不符合
		} else {
			return Rule.Inapplicable;
		}
	}

	@Override
	public Object deviseRightSolution(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object examine(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if ( this.applicable(objects) == Rule.Inapplicable) return Rule.Inapplicable;
		
		_NPTuple npt = (_NPTuple) objects[1];
		Tree NP = npt.getNP();

		TregexPattern pattern = null;
		TregexMatcher matcher = null;

		/*
		 * 名词短语中含有的冠词，也可能没有
		 */
		Tree dt = null;
		sb.clear();
		sb.append("/\\bDT\\b/");
		pattern = TregexPattern.compile(sb.toString());
		matcher = pattern.matcher(NP);
		
		/*
		 * 名词短语中
		 */
		sb.clear();
		for( TaggedWord tw : NP.taggedYield()) {
			sb.append(tw.word()).append(" ");
		}
		
		if ( this.Island.matcher(sb.toString()).find()) {
			if ( this.TheIsland.matcher(sb.toString()).find()) {
				if ( sb.toString().trim().startsWith("the") || sb.toString().trim().startsWith("The")) {
					return null;
				} else {
					BadEgg egg = new BadEgg();
					egg.whereIsWrong = NP;
					egg.setProperty(BadEgg.Error);
					egg.setViolatedRule(this);
					return egg;	
				}							
			} else {
				if ( matcher.find()) {
					BadEgg egg = new BadEgg();
					egg.whereIsWrong = NP;
					egg.setProperty(BadEgg.Error);
					egg.setViolatedRule(this);
					return egg;						
				} else {
					return null;
				}
			}
		} else if ( this.Islands.matcher(sb.toString()).find()) {
			if ( this.NoTheIslands.matcher(sb.toString()).find()) {
				if ( matcher.find()) {
					BadEgg egg = new BadEgg();
					egg.whereIsWrong = NP;
					egg.setProperty(BadEgg.Error);
					egg.setViolatedRule(this);
					return egg;						
				} else {
					return null;
				}				
			} else {
				if ( sb.toString().trim().startsWith("the") || sb.toString().trim().startsWith("The")) {
					return null;
				} else {
					BadEgg egg = new BadEgg();
					egg.whereIsWrong = NP;
					egg.setProperty(BadEgg.Error);
					egg.setViolatedRule(this);
					return egg;	
				}				
			}
		} else {
			if ( this.NoTheNoBoth.matcher(sb.toString()).find()) {
				if ( matcher.find()) {
					BadEgg egg = new BadEgg();
					egg.whereIsWrong = NP;
					egg.setProperty(BadEgg.Error);
					egg.setViolatedRule(this);
					return egg;						
				} else {
					return null;
				}				
			} else if ( this.TheNoBoth.matcher(sb.toString()).find()) {
				if ( sb.toString().trim().startsWith("the") || sb.toString().trim().startsWith("The")) {
					return null;
				} else {
					BadEgg egg = new BadEgg();
					egg.whereIsWrong = NP;
					egg.setProperty(BadEgg.Error);
					egg.setViolatedRule(this);
					return egg;	
				}				
			} else {
				return Rule.Inapplicable;
			}
		}
	}

	@Override
	public Object whyItsWrong(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		sb.append("<p>");
		sb.append("群岛前面一般要加定冠词。");
		sb.append("</p>");			
		return sb.toString();
	}
}
